#include "SEnum.h"

#include "ExpressionResolutor.h"

SEnum::SEnum( SEnumTypeDescriptorSp typeDescriptor, string value )
{
	this->typeDescriptor = typeDescriptor;
	Set(value);
}

#include <iostream>
SEnumSp SEnum::Parse(SEnumTypeDescriptorSp typeDescriptor, string s)
{
	if (!typeDescriptor || (typeDescriptor && !typeDescriptor->IsValid()))
	{
		throw SArgumentException("The enum type descriptor is not valid.");
	}

	trim(s);

	// Check if s is a numeric value and try to make a lookup
	unsigned long n;

	try
	{
		n = SNumber::Parse(s)->Get();
	}
	catch(...)
	{
		// s is the 
		return SEnum::Create( typeDescriptor, s );
	}

	return SEnum::Create(typeDescriptor, n);
}

SEnumSp SEnum::Create( SEnumTypeDescriptorSp typeDescriptor, string val )
{
	if ( !typeDescriptor || (typeDescriptor && !typeDescriptor->IsValid()) )
	{
		throw SArgumentException("The enum type descriptor is not valid.");
	}
	if ( !typeDescriptor->IsDefined(val) )
	{
		throw SArgumentException("The value '" + val + "' is not defined");
	}

	return SEnumSp(new SEnum(typeDescriptor, val));
}

SEnumSp SEnum::Create( SEnumTypeDescriptorSp typeDescriptor, unsigned long val )
{
	if ( !typeDescriptor || (typeDescriptor && !typeDescriptor->IsValid()) )
	{
		throw SArgumentException("The enum type descriptor is not valid.");
	}
	if ( !typeDescriptor->IsDefined(val) )
	{
		ostringstream os;
		os << "The numeric value '" << val << "' is not defined.";
		throw SArgumentException( os.str() );
	}

	string key = typeDescriptor->GetValue(val);

	return SEnumSp(new SEnum(typeDescriptor, key));
}

void SEnum::Set( string value )
{
	if ( !typeDescriptor->IsDefined(value) )
	{
		throw SArgumentException("The key is not valid.");
	}

	this->value = value;
}

void SEnum::Set( unsigned long value )
{
	if ( !typeDescriptor->IsDefined(value) )
	{
		throw SArgumentException("The value is not valid.");
	}

	this->value = typeDescriptor->GetValue(value);
}